package Bencode

import (
	"bufio"
	"fmt"
	"io"
	"reflect"
	"strconv"
)

// EncodeString 将参数str编码后，写入io.Writer
// 编码例子： abc ===> 3:abc
func EncodeString(w io.Writer, str string) (int, error) {
	byteLen := len(str)
	writer := bufio.NewWriter(w)
	//数组转化为字符串写入
	writer.WriteString(strconv.Itoa(byteLen))
	writer.WriteByte(':')
	writer.WriteString(str)

	if err := writer.Flush(); err != nil {
		return 0, err
	}
	return byteLen + 2, nil
}

// DecodeString 从io.Reader读取后解码，并返回
// 3:abc ==> abc
func DecodeString(r io.Reader) (str string, err error) {
	reader := bufio.NewReader(r)

	//开头的是否是数字
	byteLen, err := reader.ReadByte()
	if reflect.TypeOf(byteLen).Kind() != reflect.Int { //如果不是数字
		return "", ErrorType
	}

	//再读一个字节，判断是不是冒号
	curByte, err := reader.ReadByte()
	if err != nil {
		return "", err
	}
	if curByte != ':' {
		return "", ErrorType
	}

	//读取num位字节
	len, err := strconv.Atoi(string(byteLen))
	if err != nil {
		return "", err
	}
	buffer := make([]byte, len)
	_, err = io.ReadAtLeast(r, buffer, len)
	str = string(buffer)
	return
}

// EncodeInt 编码整形数字
// 例子：123 ==> i123e
func EncodeInt(w io.Writer, num int) (writedByteLen int, err error) {
	writer := bufio.NewWriter(w)
	str := strconv.Itoa(num)
	encodeStr := fmt.Sprintf("i%se", str)
	writedByteLen, err = writer.WriteString(encodeStr)
	writer.Flush()
	return
}

// DecodeInt 解码整形数字
//  例子：i123e ===> 123
func DecodeInt(r io.Reader) (num int, err error) {
	reader := bufio.NewReader(r)
	firstByte, err := reader.ReadByte()
	if err != nil {
		return 0, err
	}
	if firstByte != 'i' {
		return 0, ErrorType
	}

	var res []byte
	for {
		buffer := make([]byte, 1)
		_, err := reader.Read(buffer)
		if err == io.EOF {
			break
		}
		res = append(res, buffer...)
	}
	num, err = strconv.Atoi(string(res))
	return
}
